from django.shortcuts import render, redirect
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django import http
from django.conf import settings
from django.contrib.auth import login
import re
from django_redis import get_redis_connection

from meiduo_mall.utils.response_code import RETCODE
from .models import OAuthQQUser
from users.models import User
from .utils import generate_openid_sign, check_openid
import logging
from carts.utils import merge_cart_cookie_to_redis

logger = logging.getLogger('django')



class QQOAuthURLView(View):
    """拼接QQ登录url"""
    def get(self, request):
        # 1.获取查询参数
        next = request.GET.get('next') or '/'

        # 2.创建QQ登录工具对象
        # auth_obj = OAuthQQ(client_id=appid, client_secret=appkey, redirect_uri=回调地址, state=当成next)
        # auth_obj = OAuthQQ(client_id='101518219',
        #                    client_secret='418d84ebdc7241efb79536886ae95224',
        #                    redirect_uri='http://www.meiduo.site:8000/oauth_callback',
        #                    state=next)
        auth_obj = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                           client_secret=settings.QQ_CLIENT_SECRET,
                           redirect_uri=settings.QQ_REDIRECT_URI,
                           state=next)
        # 3.调用SDK中 get_qq_url方法获取到拼接好的QQ登录url
        login_url = auth_obj.get_qq_url()

        # 4.响应json
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'login_url': login_url})


class QQOAuthUserView(View):
    """QQ登录成功回调处理"""

    def get(self, request):
        # 1.接收查询参数
        code = request.GET.get('code')
        # 2.校验
        if code is None:
            return http.HttpResponseForbidden('缺少必传参数')

        # 创建QQ登录工具对象
        auth_obj = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                           client_secret=settings.QQ_CLIENT_SECRET,
                           redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 通过code获取access_token
            access_token = auth_obj.get_access_token(code)
            # 通过access_token 获取openid
            openid = auth_obj.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError('oAuth2.0认证失败')

        # 查询openid是否绑定过用户
        try:
            oAuth_model = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 包装传入模板渲染的数据
            data = {'openid': generate_openid_sign(openid)}  # 要将openid加密后再渲染
            # 如果openid没有绑定用户,给用户展示绑定界面
            return render(request, 'oauth_callback.html', data)
        else:
            # 如果openid已绑定用户,直接代码登录成功...
            # 查询openid关联的user
            user = oAuth_model.user
            # 状态保持
            login(request, user)
            # 重定向到指定来源
            response = redirect(request.GET.get('state') or '/')
            # 调用合并购物车函数
            merge_cart_cookie_to_redis(request, response)
            # 存储cookie username
            response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
            return response

    def post(self, request):
        """openid绑定用户处理"""
        # 1.接收表单数据
        query_dict = request.POST
        mobile = query_dict.get('mobile')
        password = query_dict.get('password')
        sms_code = query_dict.get('sms_code')
        openid = query_dict.get('openid')
        # 2.校验
        if all([mobile, password, sms_code, openid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20密码')

        redis_cli = get_redis_connection('verify_codes')
        sms_code_server = redis_cli.get('sms_%s' % mobile)
        if sms_code_server is None:
            return http.HttpResponseForbidden('短信验证码已过期')
        if sms_code != sms_code_server.decode():
            return http.HttpResponseForbidden('请输入正确的短信验证码')

        # 将openid解密
        openid = check_openid(openid)
        if openid is None:
            return http.HttpResponseForbidden('openid无效')

        # 3.绑定用户
        # 拿mobile查询User
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果mobile没有查询到,说明是新用户,就创建一个新user再和openid绑定
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 如果mobile能查询到,说明是已注册的老用户,再校验密码,
            if user.check_password(password) is False:
                return http.HttpResponseForbidden('QQ绑定用户失败')


        # 如果代码执行到此,绝对有用户了,然后就和openid进行绑定
        OAuthQQUser.objects.create(
            openid=openid,
            user=user
        )

        # 绑定成功即代表登录成功
        login(request, user)
        response = redirect(request.GET.get('state') or '/')
        # 调用合并购物车函数
        merge_cart_cookie_to_redis(request, response)

        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        return response

